#include "bsp_spi.h"
uint8_t SPI1_txbuf[TX_LEN],SPI1_rxbuf[RX_LEN];

// const SPI_TypeDef SPI_UNIT_MAP[1] = {
//     SYM_SPI1,
// //    SYM_SPI2,
// };
const uint32_t SPI_MODE_MAP[2] = {
    SPI_WORKMODE_MASTER,
    SPI_WORKMODE_SLAVE,
};
const uint32_t SPI_CLKDIV_MAP[8] = {
    SPI_SCKSRC_PCLKDIV2,
    SPI_SCKSRC_PCLKDIV4,
    SPI_SCKSRC_PCLKDIV8,
    SPI_SCKSRC_PCLKDIV16,
    SPI_SCKSRC_PCLKDIV32,
    SPI_SCKSRC_PCLKDIV64,
    SPI_SCKSRC_PCLKDIV128,
    SPI_SCKSRC_PCLKDIV256,
};
const uint32_t SPI_CPHA_MAP[2] = {
    SPI_SCKPHASE_1EDGE,
    SPI_SCKPHASE_2EDGE,
};
const uint32_t SPI_CPOL_MAP[2] = {
    SPI_SCKPOLARITY_NEGATIVE,
    SPI_SCKPOLARITY_POSITIVE,
};
const uint32_t SPI_DATAWIDTH_MAP[13] = {
    SPI_DATAWIDTH_4BIT,
    SPI_DATAWIDTH_5BIT,
    SPI_DATAWIDTH_6BIT,
    SPI_DATAWIDTH_7BIT,
    SPI_DATAWIDTH_8BIT,
    SPI_DATAWIDTH_9BIT,
    SPI_DATAWIDTH_10BIT,
    SPI_DATAWIDTH_11BIT,
    SPI_DATAWIDTH_12BIT,
    SPI_DATAWIDTH_13BIT,
    SPI_DATAWIDTH_14BIT,
    SPI_DATAWIDTH_15BIT,
    SPI_DATAWIDTH_16BIT,
};
const uint32_t SPI_FIRSTBIT_MAP[2] = {
    SPI_FIRSTBIT_MSB,
    SPI_FIRSTBIT_LSB,
};
const uint32_t SPI_Duplex_MAP[4] = {
    SPI_COMM2LINES_FullDuplex,
    SPI_COMM1LINE_TxOnly,
    SPI_COMM1LINE_RxOnly,
    SPI_COMM1LINE_HalfDuplex,
};
const uint32_t SPI_CS_MODE_MAP[3] = {
    SPI_NCS_HARD_OUTPUT,
    SPI_NCS_HARD_INPUT,
    SPI_NCS_SOFT,
};
int32_t bsp_spi_param_check(bsp_spi_init_t *spi_instance)
{
    if(spi_instance == NULL)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->cs_pin == NULL)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->sck_pin == NULL)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->miso_pin == NULL)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->mosi_pin == NULL)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->mode >= 2)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->div >= 8)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->cpol >= 2)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->cpha >= 2)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->datawidth >= 13)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->firstbit >= 2)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->duplex >= 4)
    {
        return BSP_BADPARA;
    }
    if(spi_instance->cs_mode >= 3)
    {
        return BSP_BADPARA;
    }
    return BSP_OK;
}
int32_t bsp_Spi_Init(bsp_spi_init_t *spi_instance)
{
    if(bsp_spi_param_check(spi_instance) != BSP_OK)
    {
        return BSP_BADPARA;
    }
    HAL_SYSCTRL_SPI1_CLK_ENABLE();//enable spi1 clock
    /*configure SPI*/
    SYM_SPI1->CR1 = SPI_MODE_MAP[spi_instance->mode] |\
    SPI_CPOL_MAP[spi_instance->cpol] |\
    SPI_CPHA_MAP[spi_instance->cpha]|\
    SPI_CLKDIV_MAP[spi_instance->div] |\
    SPI_DATAWIDTH_MAP[spi_instance->datawidth] |\
    SPI_FIRSTBIT_MAP[spi_instance->firstbit] |\
    SPI_Duplex_MAP[spi_instance->duplex] |\
    SPI_CS_MODE_MAP[spi_instance->cs_mode];
    SYM_SPI1->CR2 |= 0x01;//enable spi;
    /*configure SPI pins*/
    bsp_gpio_init(spi_instance->cs_pin);
    bsp_gpio_init(spi_instance->sck_pin);
    bsp_gpio_init(spi_instance->miso_pin);
    bsp_gpio_init(spi_instance->mosi_pin);
    return 0;
}

int32_t bsp_Spi_DeInit(bsp_spi_init_t *spi_instance)
{
    SYM_SYSCTRL->APBRST1_f.SPI1 = 0; //reset spi1
    SYM_SYSCTRL->APBRST1_f.SPI1 = 1; //resume spi1
    HAL_SYSCTRL_SPI1_CLK_DISABLE();
    return 0;
}

int32_t bsp_spi_transmit(bsp_spi_init_t *spi_instance, uint8_t *tx_buf, uint8_t *rx_buf, uint16_t len)
{
    volatile uint32_t u32RxCnt = 0, u32TxCnt = 0;
    if(tx_buf == NULL)
    {
        return BSP_BADPARA;
    }
    if(rx_buf == NULL)
    {
        return BSP_BADPARA;
    }
    if(len == 0)
    {
        return BSP_BADPARA;
    }
    SYM_SPI1->SSI_f.SSI = 0;
    while(u32RxCnt < len)
    {
        if(u32TxCnt < len)
        {
            if((SYM_SPI1->ISR_f.TXE) ==  1)
            {
                SYM_SPI1->DR = tx_buf[u32TxCnt];
                u32TxCnt++;
            }
        }

        if((SYM_SPI1->ISR_f.RXNE) == 1)
        {
            rx_buf[u32RxCnt] = SYM_SPI1->DR;
            u32RxCnt++;
        }
    }
    // uint32_t i = 0;
    // for(i = 0; i < len; i++)
    // {
    //     SYM_SPI1->DR = tx_buf[i];
    //     while((SYM_SPI1->ISR_f.TXE) == 0);
    //     while((SYM_SPI1->ISR_f.RXNE) == 0);
    //     rx_buf[i] = SYM_SPI1->DR;
    // }
    SYM_SPI1->SSI_f.SSI = 1;
    return BSP_OK;
}
